-module(bnode_selector).
-include("btree.hrl").

%% API
-export([forward/2]).
-export([backward/2]).

forward(#bt{nodes = Nodes} = BTree, BNode) ->
    case BNode of
        #bn{id = NodeId, children = [FirstNode | RemChildren]} ->
            BNode1 = BNode#bn{status = #{children => RemChildren}},
            BTree1 = BTree#bt{nodes = maps:put(NodeId, BNode1, Nodes)},
            bnode_api:forward(BTree1, FirstNode);
        _ ->    % 没有子节点要判断，直接返回
            backward(BTree#bt{result = ?SUCCESS}, BNode)
    end.

%% 子节点成功返回，直接返回失败
backward(#bt{result = ?SUCCESS, nodes = Nodes} = BTree, BNode) ->
    #bn{id = NodeId} = BNode,
    BNode1 = BNode#bn{status = #{}},
    BTree1 = BTree#bt{
        result = ?SUCCESS,
        nodes = maps:put(NodeId, BNode1, Nodes)
    },
    bnode_api:backward(BTree1, BNode1);
%% 子节点失败返回，还有子节点就继续，否则返回失败
backward(#bt{result = ?FAILURE, nodes = Nodes} = BTree, BNode) ->
    #bn{id = NodeId, status = Status} = BNode,
    case maps:get(children, Status, []) of
        [Child | Rem] ->    % 还有子节点需要走
            BNode1 = BNode#bn{status = maps:put(children, Rem, Status)},
            BTree1 = BTree#bt{nodes = maps:put(NodeId, BNode1, Nodes)},
            bnode_api:forward(BTree1, Child);
        _ ->                % 没有子节点了，返回failure
            BNode1 = BNode#bn{status = #{}},
            BTree1 = BTree#bt{
                result = ?FAILURE,
                nodes = maps:put(NodeId, BNode1, Nodes)
            },
            bnode_api:backward(BTree1, BNode1)
    end.